﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MediaPortal.GUI.Library;
using MediaPortal.Dialogs;

namespace Burn4You
{
    #region Types

    public enum DiskType
    {
        CD,
        VCD,
        SVCD,
        DVD,
        BluRay
    }

    public enum StreamType
    {
        Audio,
        Video,
        Subtitle
    }

    /// <summary>
    /// List of Burn4You screens
    /// </summary>
    public enum Screen
    {
        FileSelection = 54264,
        DiskType = 54265,
        ProgressScreen = 54266,
        TemplateSelection = 54267
    }

    #endregion

    #region Objects

    public struct PluginReturnInfo
    {
        /// <summary>
        /// Path to Folder or ISO
        /// </summary>
        public String Path;

        /// <summary>
        /// Label to use for the disk
        /// </summary>
        public String Label; 

        /// <summary>
        /// Type of disk the ISO is/should be.
        /// </summary>
        public DiskType DiskType;

        /// <summary>
        /// The Extension finished. If false the plugin will go back to the burn type selection screen.
        /// </summary>
        public bool Completed;
    }

    public class BurnType
    {
        public String Name;
        public String Image;
        public List<int> SupportingExtenstions;
        public int ID;
    }

    public struct BurnFile
    {
        /// <summary>
        /// Full Path to file. This is mandatory. 
        /// </summary>
        public String FilePath;
        /// <summary>
        /// What type of file is it. EG "Movie" or "TV Show". This is mandatory.
        /// </summary>
        public String BurnType;
        /// <summary>
        /// The size of the file in bytes
        /// </summary>
        public double Size;
        /// <summary>
        /// The total playtime of the file in miliseconds
        /// </summary>
        public double PlayTime;
        /// <summary>
        /// The reader friendly name or title of the file
        /// </summary>
        public String Name;
        /// <summary>
        /// List of Audio streams
        /// </summary>
        public List<CodecStream> AudioStreams;
        /// <summary>
        /// List of Video streams
        /// </summary>
        public List<CodecStream> VideoStreams;
        /// <summary>
        /// List of Subtitle streams
        /// </summary>
        public List<CodecStream> SubtitleStreams;
        /// <summary>
        /// Name of a relating item to a file. E.G. The name of the TV Show the file belongs to, or the name of the album the song belongs to etc..
        /// </summary>
        public String GroupName;
    }

    public struct CodecStream
    {
        /// <summary>
        /// The type of the stream.
        /// </summary>
        public StreamType Type;
        /// <summary>
        /// Stream number
        /// </summary>
        public int StreamNo;
        /// <summary>
        /// The codec of the stream
        /// </summary>
        public String codec;
        /// <summary>
        /// The width of the video resolution
        /// </summary>
        public int Width;
        /// <summary>
        /// The height of the video resolution
        /// </summary>
        public int Height;
        /// <summary>
        /// Frame rate of the stream
        /// </summary>
        public decimal Framerate;
    }

    #endregion

    public class Burn4YouPlugin : GUIWindow, ISetupForm
    {
        private enum MainScreen
        {
            BurnTypeSelection,
            ExtensionSelection
        }

        #region  GUI Controls

        [SkinControlAttribute(1)]        protected GUIThumbnailPanel ThumbnailPanel = null;
        
        // Dummy controls for controlling visibilty of controls.
        [SkinControlAttribute(1232)]        protected GUILabelControl dummyBurnTypeScreen = null;
        [SkinControlAttribute(1233)]        protected GUILabelControl dummyExtScreen = null;

        #endregion

        #region variables

        public static Burn4YouSettings settings = null;
        public static ExtensionHandler ExtHandler = null;
        public static EncoderHelper MediaEncoderHelper = null;
        public static List<BurnType> BurnTypes = null;
        /// <summary>
        /// This holds a list of all the known files that can be burnt. The extensions fill this list.
        /// The first value should be the full path to the file. The second value should specifiy the BurnType, eg "TV Show" or "Movie", etc.
        /// </summary>
        public static List<BurnFile> Files = null;
        MainScreen CurrentScreen = MainScreen.BurnTypeSelection;


        #endregion

        public Burn4YouPlugin()
        {


        }

        #region ISetupForm Members

        // Returns the name of the plugin which is shown in the plugin menu
        public string PluginName()
        {
          return "Burn4You";
        }

        // Returns the description of the plugin is shown in the plugin menu
        public string Description()
        {
          return "Burns media in mediaportal to optic disks";
        }

        // Returns the author of the plugin which is shown in the plugin menu
        public string Author()
        {
          return "Craige1";
        }

        // show the setup dialog
        public void ShowPlugin()
        {
            FrmConfig frmConfig = new FrmConfig();
            frmConfig.ShowDialog();
        }

        // Indicates whether plugin can be enabled/disabled
        public bool CanEnable()
        {
          return true;
        }

        // Get Windows-ID
        public int GetWindowId()
        {
          // WindowID of windowplugin belonging to this setup
          // enter your own unique code
          return 54263;
        }

        // Indicates if plugin is enabled by default;
        public bool DefaultEnabled()
        {
          return true;
        }

        // indicates if a plugin has it's own setup screen
        public bool HasSetup()
        {
          return true;
        }

        /// <summary>
        /// If the plugin should have it's own button on the main menu of MediaPortal then it
        /// should return true to this method, otherwise if it should not be on home
        /// it should return false
        /// </summary>
        /// <param name="strButtonText">text the button should have</param>
        /// <param name="strButtonImage">image for the button, or empty for default</param>
        /// <param name="strButtonImageFocus">image for the button, or empty for default</param>
        /// <param name="strPictureImage">subpicture for the button or empty for none</param>
        /// <returns>true : plugin needs it's own button on home
        /// false : plugin does not need it's own button on home</returns>

        public bool GetHome(out string strButtonText, out string strButtonImage,
          out string strButtonImageFocus, out string strPictureImage)
        {
          strButtonText = PluginName();
          strButtonImage = String.Empty;
          strButtonImageFocus = String.Empty;
          strPictureImage = String.Empty;
          return true;
        }

        // With GetID it will be an window-plugin / otherwise a process-plugin
        // Enter the id number here again
         public override int GetID
        {
          get
          {
              return 54263;
          }
        }


        #endregion

        #region MediaPortal overrides

        public override bool Init()
        {
            Utils.Burn4YouLog.Write("Burn4You initialzing");

            MediaEncoderHelper = new EncoderHelper();

            // Init Lists
            BurnTypes = new List<BurnType>();
            Files = new List<BurnFile>();


            try
            {
                settings = new Burn4YouSettings();
                ExtHandler = new ExtensionHandler();
            }
            catch (Exception ex)
            {
                Utils.Burn4YouLog.Write(ex.ToString());
            }

            foreach (Extension ext in Burn4YouPlugin.ExtHandler.Extensions)
                Utils.Burn4YouLog.Write("Extensions: " + ext.ExtInterface.ExtName);

            foreach (BurnType burntype in BurnTypes)
                Utils.Burn4YouLog.Write("BurnType: " + burntype.Name + " Image: " + burntype.Image);

            foreach (BurnFile file in Files)
                Utils.Burn4YouLog.Write("File: " + file.Name + " | Type: " + file.BurnType + " | Path: " + file.FilePath);

            return Load(GUIGraphicsContext.Skin + @"\Burn4You.xml");
        }

        //This method gets called just before your plugin is shown. You can use it to setup the screen like setting checkboxes, filling lists, etc, etc.
        protected override void OnPageLoad()
        {
            Utils.Burn4YouLog.Write("OnPageLoad called. Previous window: " + GUIWindowManager.GetPreviousActiveWindow().ToString());

            FillBurnTypeThumbnailPanel();

            base.OnPageLoad();
        }

        //This method gets called when the user switches to another screen (it happens). You can use it to clean up, store any settings, etc. The newWindowId will contain the id of the screen the user is switching to.
        protected override void OnPageDestroy(int new_windowId)
        {
            MediaEncoderHelper.Stop();
            base.OnPageDestroy(new_windowId);
        }

        // This method gets called if the user presses the show context menu key/button. Normally this is F9 on the keyboard. You can use it to show context menu's you see all over MediaPortal.
        protected override void OnShowContextMenu()
        {

            base.OnShowContextMenu();
        }

        // When the user is interacting with your screen, this method will be called on a regular basis. You can use it to do some processing like refreshing (parts) of the screen.
        public override void Process()
        {

            base.Process();
        }

        //This method gets called when the user presses a button or selects something from a list. controlId will contain the id of the control which is pressed. control will contain the GUIControl object. actionType will contain which action was done (like select, queue, delete, etc.).
        protected override void OnClicked(int controlId, GUIControl control, MediaPortal.GUI.Library.Action.ActionType actionType)
        {
            if (control == ThumbnailPanel)
            {
                Utils.Burn4YouLog.Write("Received click on Thumbnailpanel");
                
                GUIListItem item = ThumbnailPanel.SelectedListItem;

                if (CurrentScreen == MainScreen.BurnTypeSelection)
                {
                    Utils.Burn4YouLog.Write("Click was on BurnType Selection screen");

                    BurnType bt = (BurnType)item.TVTag;

                    foreach (BurnType bti in BurnTypes)
                    {
                        if (bti.ID == bt.ID)
                        {
                            Utils.Burn4YouLog.Write("Burn Type selected is: " + bti.Name);
                            BurnTypeSelected(bti);
                            return;
                        }
                    }
                }
            }


            base.OnClicked(controlId, control, actionType);
        }

        #endregion

        #region Functions

        private void BurnTypeSelected(BurnType bt)
        {
            List<Extension> SupportedExts = GetExtensionsforBurnType(bt, true);

            if (SupportedExts.Count > 1)
            {
                Utils.Burn4YouLog.Write("Burn Type has more then one supporting extension.");

                HideAllControls();
                dummyExtScreen.Visible = true;

                FillExtThumbnailPanel(bt);

                return;
            }

            Utils.Burn4YouLog.Write("Burn Type only has one supporting extension.");
            // Since we know theres only 1 from the check above, then we just choose the first one in the list, then show it.
            ShowExtension(SupportedExts[0]);
        }     

        private void ShowExtension(Extension ext)
        {
            Utils.Burn4YouLog.Write("Showing extension: " + ext.ExtInterface.ExtName);

            GUIWindow window = GUIWindowManager.GetWindow(54270);
            if (window == null)
                Utils.Burn4YouLog.Write("Window is null");

            GUIWindowManager.ActivateWindow(54270, false);
        }

        private void FillBurnTypeThumbnailPanel()
        {
            ThumbnailPanel.Clear();

            foreach (BurnType bt in BurnTypes)
            {
                GUIListItem item = new GUIListItem();

                item.ThumbnailImage = bt.Image;
                item.Label = bt.Name;
                item.TVTag = bt;

                ThumbnailPanel.Add(item);
            }
        }

        private void FillExtThumbnailPanel(BurnType bt)
        {
            ThumbnailPanel.Clear();

            foreach (Extension ext in GetExtensionsforBurnType(bt, true))
            {
                GUIListItem item = new GUIListItem();

                item.ThumbnailImage = ext.ExtInterface.Image;
                item.Label = ext.ExtInterface.ExtName;
                item.TVTag = ext;

                ThumbnailPanel.Add(item);
            }
        }

        #endregion

        #region helpers

        public static List<String> GetBurnTypes()
        {
            List<String> BurnTypesStringList = new List<String>();

            foreach (BurnType bt in BurnTypes)
            {
                BurnTypesStringList.Add(bt.Name);
            }

            return BurnTypesStringList;
        }

        public void HideAllControls()
        {
            dummyBurnTypeScreen.Visible = false;
            dummyExtScreen.Visible = false;
        }

        private List<Extension> GetExtensionsforBurnType(BurnType bt, bool OnlyWithUI)
        {
            Utils.Burn4YouLog.Write("Getting list of extensions that support burn type: " + bt.Name);

            List<Extension> exts = new List<Extension>();

            foreach (Extension ext in ExtHandler.Extensions)
            {
                if (OnlyWithUI && !ext.ExtInterface.HasUI)
                    continue;

                foreach (int SupportedExtID in bt.SupportingExtenstions)
                {
                    if (SupportedExtID == ext.ID)
                    {
                        Utils.Burn4YouLog.Write("Extension \"" + ext.ExtInterface.ExtName +"\" is a supported extension for burn type: " + bt.Name);
                        exts.Add(ext);
                    }
                }
            }

            return exts;
        }

        /// <summary>
        /// Returns a list of known files that are of the type(s) specified. Seperate the types with a , in the supplied string.
        /// </summary>
        /// <param name="Types">Supply a string with the type(s) you want returned EG "Movie,TV Show,Music". Use a , to spereate more then one type.</param>
        /// <returns>List of Files that fit the types requested.</returns>
        public static List<BurnFile> GetBurnFilesByType(String Types)
        {
            List<BurnFile> supportedfiles = new List<BurnFile>();

            String[] TypesList = Types.Split(',');

            foreach (BurnFile file in Files)
            {
                foreach (String type in TypesList)
                {
                    if (file.BurnType == type)
                        supportedfiles.Add(file);
                }
            }

            return supportedfiles;
        }

        #endregion
    }
}
